﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.Collections;
using TTMain.UI;
using TTData;

namespace TTMain.Net
{   

    public class GameNet
    {
        private bool _isConnected;
        private TcpListener tcpListener;
        Thread threadListeningforConnections;
        public static ManualResetEvent tcpClientConnected = new ManualResetEvent(false);
        private String _serverIp;
        private Int32 _serverPort;
        private GameUI _gameUI;

        #region Network Message Type Constants
        private const Int16 MESSAGE_DISCOVER =              0;
        private const Int16 MESSAGE_CREATE_TABLE =          1;
        private const Int16 MESSAGE_JOIN_TABLE =            2;
        private const Int16 MESSAGE_START_GAME =            3;
        private const Int16 MESSAGE_CANCEL_GAME =           4;
        private const Int16 MESSAGE_CHANGE_CARDS =          5;
        private const Int16 MESSAGE_DRAW_CARD =             6;
        private const Int16 MESSAGE_PUT_CARD =              7;
        private const Int16 MESSAGE_CONTINUE =              8;
        private const Int16 MESSAGE_SCORE =                 9;
        private const Int16 MESSAGE_SCORE_HELP =            10;
        private const Int16 MESSAGE_DISCARD_CARDS =         11;
        private const Int16 MESSAGE_PUT_HOUSES =            12;
        private const Int16 MESSAGE_QUIT =                  13;
        private const Int16 MESSAGE_OFFER =                 14;
        private const Int16 MESSAGE_NACK_OFFER =            15;
        private const Int16 MESSAGE_ACK_JOIN_TABLE =        16;
        private const Int16 MESSAGE_NACK_JOIN_TABLE =       17;
        private const Int16 MESSAGE_USER_JOIN_TABLE =       18;
        private const Int16 MESSAGE_USER_START =            19;
        private const Int16 MESSAGE_USER_CANCEL =           20;
        private const Int16 MESSAGE_GAME_START =            21;
        private const Int16 MESSAGE_USER_TURN =             22;
        private const Int16 MESSAGE_ACK_CREATE_TABLE =      23;
        private const Int16 MESSAGE_NACK_CREATE_TABLE =     24;
        private const Int16 MESSAGE_DISCARD_PUBLIC_CARDS =  25;
        private const Int16 MESSAGE_PLAYERS =               26;
        private const Int16 MESSAGE_DISCONNECT =            27;
        #endregion

        /// <summary>
        /// Create a new Game Net object that handles communication to the game server
        /// </summary>
        /// <param name="serverIp">the server's IP address</param>
        /// <param name="serverPort">the server's port</param>
        public GameNet(GameUI gameUI, String serverIp, Int32 serverPort)
        {
            _serverIp = serverIp;
            _serverPort = serverPort;
            _gameUI = gameUI;
            _isConnected = false;
        }

        /// <summary>
        /// Opens a port to listen for updates from the game server
        /// </summary>
        /// <param name="port">the local port on which the server connects</param>
        /// <returns>whether the operation was or not successful</returns>
        public bool OpenConnection(Int32 port)
        {
            try
            {
                tcpListener = new TcpListener(IPAddress.Any, port);
                threadListeningforConnections = new Thread(new ThreadStart(StartListening));
                threadListeningforConnections.Start();                
                return true;
            }
            catch (Exception)
            {
                _isConnected = false;
                _gameUI.HandleSocketError();
                return false;
            }
        }

        /// <summary>
        /// Checks to see whether the object is listening the TCP port 
        /// </summary>
        /// <returns>true if the object listening, false otherwise</returns>
        public bool IsConnected()
        {
            return _isConnected;
        }
        
        /// <summary>
        /// Listens for new TCP packets 
        /// </summary>
        private void StartListening()
        {
            _isConnected = true;
            try
            {
                tcpListener.Start();
                while (_isConnected)
                {
                    tcpListener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptTcpClientCallback), tcpListener);
                    tcpClientConnected.WaitOne();
                    tcpClientConnected.Reset();
                }
            }
            catch (SocketException)
            {
                _isConnected = false;
                _gameUI.HandleSocketError();
            }
        }

        /// <summary>
        /// Closes the listening socket and no more connections will be accepted
        /// </summary>
        public void CloseConnection()
        {
            if (_isConnected)
            {
                _isConnected = false;
                tcpClientConnected.Close();
                threadListeningforConnections.Abort();
            }
        }
        
        /// <summary>
        /// Receives a connection on the listening port and handles it
        /// </summary>
        /// <param name="ar"></param>
        private void DoAcceptTcpClientCallback(IAsyncResult ar)
        {            
            TcpListener listener = (TcpListener)ar.AsyncState;            
            TcpClient client = listener.EndAcceptTcpClient(ar);
            HandleClientComm(client);            
            tcpClientConnected.Set();
        }

        /// <summary>
        /// Concatenates all the bytes of the TCP client
        /// </summary>
        /// <param name="client"></param>
        private void HandleClientComm(object client)
        {            
            int i;

            try
            {
                Byte[] bytes = new Byte[524288];
                Byte[] buffer = null;
                Byte[] bytes_data = null;

                TcpClient tcpClient = (TcpClient)client;
                NetworkStream stream = tcpClient.GetStream();

                if (stream != null)
                {

                    while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                    {
                        if (buffer != null)
                        {
                            bytes_data = new Byte[buffer.Length + i];
                            buffer.CopyTo(bytes_data, 0);
                            for (int j = 0; j < i; j++)
                                bytes_data[j + buffer.Length] = bytes[j];
                        }
                        else
                        {
                            bytes_data = new Byte[i];
                            for (int j = 0; j < i; j++)
                                bytes_data[j] = bytes[j];
                        }
                        buffer = bytes_data;
                    }

                    ParseTCPMEssages(bytes_data);
                }

                tcpClient.Close();
                
            }
            catch (Exception)
            {
                _gameUI.HandleTcpClientError();
            }
        }

        /// <summary>
        /// Parses the infomation in a steam of bytes
        /// </summary>
        /// <param name="data">the stream of bytes to be parsed</param>
        private void ParseTCPMEssages(Byte[] data)
        {
            Int32 data_type;
            String data_nickname, data_data;

            String data_string = System.Text.Encoding.ASCII.GetString(data);

            int val1 = data_string.IndexOf(":");
            data_string = data_string.Substring(val1 + 1);
            val1 = data_string.IndexOf(":");

            String type = data_string.Substring(0, val1);
            try {
                data_type = Convert.ToInt32(type);
            }
            catch (Exception) {
                return;
            }

            data_string = data_string.Substring(val1 + 1);
            val1 = data_string.IndexOf(":");

            data_nickname = data_string.Substring(0, val1);
            data_string = data_string.Substring(val1 + 1);
            val1 = data_string.IndexOf(":");

            data_data = data_string.Substring(0, val1);

            switch(data_type) {
                case MESSAGE_OFFER:
                    Received_Offer(data_nickname, data_data);
                    break;
                case MESSAGE_NACK_OFFER:
                    Received_Nack();
                    break;
                case MESSAGE_ACK_JOIN_TABLE:
                    Received_AckJoinTable(data_nickname, data_data);
                    break;
                case MESSAGE_NACK_JOIN_TABLE:
                    Received_NackJoinTable();
                    break;
                case MESSAGE_USER_JOIN_TABLE:
                    Received_UserJoinTable(data_nickname, data_data);
                    break;
                case MESSAGE_USER_START:
                    Received_UserStart(data_nickname);
                    break;
                case MESSAGE_USER_CANCEL:
                    Received_UserCancel(data_nickname);
                    break;
                case MESSAGE_GAME_START:
                    Received_GameStart(data_nickname, data_data);
                    break;
                case MESSAGE_CHANGE_CARDS:
                    Received_ChangeCards(data_nickname, data_data);
                    break;
                case MESSAGE_DRAW_CARD:
                    Received_DrawCard(data_nickname, data_data);
                    break;
                case MESSAGE_PUT_CARD:
                    Received_PutCard(data_nickname, data_data);
                    break;
                case MESSAGE_USER_TURN:
                    Received_UserTurn(data_nickname);
                    break;
                case MESSAGE_SCORE:
                    Received_Score(data_nickname);
                    break;
                case MESSAGE_SCORE_HELP:
                    Received_ScoreHelp(data_nickname);
                    break;
                case MESSAGE_DISCARD_CARDS:
                    Received_DiscardCard(data_nickname, data_data);
                    break;
                case MESSAGE_PUT_HOUSES:
                    Received_PutHouses(data_nickname, data_data);
                    break;
                case MESSAGE_QUIT:
                    Received_Quit(data_nickname);
                    break;
                case MESSAGE_ACK_CREATE_TABLE:
                    Received_AckCreateTable(data_data);
                    break;
                case MESSAGE_NACK_CREATE_TABLE:
                    Received_NackCreateTable();
                    break;
                case MESSAGE_DISCARD_PUBLIC_CARDS:
                    Received_DiscardPublicCards(data_nickname);
                    break;
                case MESSAGE_PLAYERS:
                    Received_Players_List(data_data);
                    break;
                case MESSAGE_DISCONNECT:
                    Received_Disconnect();
                    break;
            }
        }

        /// <summary>
        /// Sends the server a request to connect to the server using the supplied credentials
        /// </summary>
        /// <param name="nickname">the user's nickname</param>
        /// <param name="password">the user's password</param>
        public void Send_Discover(String nickname, Int32 port)
        {
            try
            {
                TcpClient client = new TcpClient(_serverIp, _serverPort);

                String message = ":-1:" + MESSAGE_DISCOVER + ":" + nickname + ":" + port + ":";
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                NetworkStream stream = client.GetStream();

                stream.Write(data, 0, data.Length);

                stream.Close();
                client.Close();
            }
            catch (Exception)
            {
                _gameUI.HandleServerDownError();
            }
        }

        /// <summary>
        /// Sends the server a request to create a new game table
        /// </summary>
        /// <param name="nickname">the user's nickname</param>
        public void Send_CreateTable(String nickname, String tableName)
        {
            try
            {
                TcpClient client = new TcpClient(_serverIp, _serverPort);

                String message = ":-1:" + MESSAGE_CREATE_TABLE + ":" + nickname + ":" + tableName + ":";
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                NetworkStream stream = client.GetStream();

                stream.Write(data, 0, data.Length);

                stream.Close();
                client.Close();
            }
            catch (Exception)
            {
                _gameUI.HandleServerDownError();              
            }
        }

        /// <summary>
        /// Sends the server a request to join an existing table
        /// </summary>
        /// <param name="nickname">the user's nickname</param>
        /// <param name="tableId">the game table id</param>
        public void Send_JoinTable(String nickname, Int32 tableId)
        {
            try
            {
                TcpClient client = new TcpClient(_serverIp, _serverPort);

                String message = ":" + tableId + ":" + MESSAGE_JOIN_TABLE + ":" + nickname + "::";
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                NetworkStream stream = client.GetStream();

                stream.Write(data, 0, data.Length);

                stream.Close();
                client.Close();
            }
            catch (Exception)
            {
                _gameUI.HandleServerDownError();               
            }
        }

        /// <summary>
        /// Sends the server a request to Start the game
        /// </summary>
        /// <param name="nickname">the user's nickname</param>
        /// <param name="tableId">the game table id</param>
        public void Send_StartGame(String nickname, Int32 tableId)
        {
            try
            {
                TcpClient client = new TcpClient(_serverIp, _serverPort);

                String message = ":" + tableId + ":" + MESSAGE_START_GAME + ":" + nickname + "::";
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                NetworkStream stream = client.GetStream();

                stream.Write(data, 0, data.Length);

                stream.Close();
                client.Close();
            }
            catch (Exception)
            {
                _gameUI.HandleServerDownError();                
            }
        }

        /// <summary>
        /// Sends the server a request to Cancel the game
        /// </summary>
        /// <param name="nickname">the user's nickname</param>
        /// <param name="tableId">the game table id</param>
        public void Send_CancelGame(String nickname, Int32 tableId)
        {
            try
            {
                TcpClient client = new TcpClient(_serverIp, _serverPort);

                String message = ":" + tableId + ":" + MESSAGE_CANCEL_GAME + ":" + nickname + "::";
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                NetworkStream stream = client.GetStream();

                stream.Write(data, 0, data.Length);

                stream.Close();
                client.Close();
            }
            catch (Exception)
            {
                _gameUI.HandleServerDownError();                
            }
        }

        /// <summary>
        /// Sends the server notification that the user changed the 6 pack visible cards
        /// </summary>
        /// <param name="nickname">the user's nickname</param>
        /// <param name="tableId">the game table id</param>
        /// <param name="cards">an array with the names of the new 6 cards</param>
        public void Send_ChangeCards(String nickname, Int32 tableId, ArrayList cards)
        {
            try
            {
                TcpClient client = new TcpClient(_serverIp, _serverPort);

                String message = ":" + tableId + ":" + MESSAGE_CHANGE_CARDS + ":" + nickname + ":";

                for (int i = 0; i < cards.Count; i++)                
                    message = message + cards[i] + "|";                
                message = message + ":";

                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                NetworkStream stream = client.GetStream();

                stream.Write(data, 0, data.Length);

                stream.Close();
                client.Close();
            }
            catch (Exception)
            {
                _gameUI.HandleServerDownError();                
            }
        }

        /// <summary>
        /// Sends the server notification that the user drew a card
        /// </summary>
        /// <param name="nickname">the user's nickname</param>
        /// <param name="tableId">the game table id</param>
        /// <param name="cardPosition">a 0-6 value representing the cards position on the table. 0 for the back card, 1-6 for the visible cards</param>
        /// <param name="cardName">the name of the card drawn if cardPosition = 0, or the name of the next card id carPosition greater than 0</param>
        public void Send_DrawCards(String nickname, Int32 tableId, Int32 cardPosition, String cardName) 
        {
            try
            {
                TcpClient client = new TcpClient(_serverIp, _serverPort);

                String message = ":" + tableId + ":" + MESSAGE_DRAW_CARD + ":" + nickname + ":" + cardPosition + "|" + cardName + ":";
                
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                NetworkStream stream = client.GetStream();

                stream.Write(data, 0, data.Length);

                stream.Close();
                client.Close();
            }
            catch (Exception)
            {
                _gameUI.HandleServerDownError();                
            }
        }

        /// <summary>
        /// Sends the server notification that the user put down a card
        /// </summary>
        /// <param name="nickname">the user's nickname</param>
        /// <param name="tableId">the game table id</param>
        /// <param name="cardPosition">a 0-1 value representing the position of the card</param>
        /// <param name="cardName">the name of the card</param>
        public void Send_PutCard(String nickname, Int32 tableId, Int32 cardPosition, String cardName)
        {
            try
            {
                TcpClient client = new TcpClient(_serverIp, _serverPort);

                String message = ":" + tableId + ":" + MESSAGE_PUT_CARD + ":" + nickname + ":" + cardPosition + "|" + cardName + ":";

                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                NetworkStream stream = client.GetStream();

                stream.Write(data, 0, data.Length);

                stream.Close();
                client.Close();
            }
            catch (Exception)
            {
                _gameUI.HandleServerDownError();                
            }
        }

        /// <summary>
        /// Sends the server notification that the user want to continue his hand
        /// </summary>
        /// <param name="nickname">the user's nickname</param>
        /// <param name="tableId">the game table id</param>
        public void Send_Continue(String nickname, Int32 tableId)
        {
            try
            {
                TcpClient client = new TcpClient(_serverIp, _serverPort);

                String message = ":" + tableId + ":" + MESSAGE_CONTINUE + ":" + nickname + "::";
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                NetworkStream stream = client.GetStream();

                stream.Write(data, 0, data.Length);

                stream.Close();
                client.Close();
            }
            catch (Exception)
            {
                _gameUI.HandleServerDownError();                
            }
        }

        /// <summary>
        /// Sends the server notification that the user wants to score on his hand
        /// </summary>
        /// <param name="nickname">the user's nickname</param>
        /// <param name="tableId">the game table id</param>
        public void Send_Score(String nickname, Int32 tableId)
        {
            try
            {
                TcpClient client = new TcpClient(_serverIp, _serverPort);

                String message = ":" + tableId + ":" + MESSAGE_SCORE + ":" + nickname + "::";
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                NetworkStream stream = client.GetStream();

                stream.Write(data, 0, data.Length);

                stream.Close();
                client.Close();
            }
            catch (Exception)
            {
                _gameUI.HandleServerDownError();                
            }
        }

        /// <summary>
        /// Sends the server notification that the user wants to score with the help
        /// </summary>
        /// <param name="nickname">the user's nickname</param>
        /// <param name="tableId">the game table id</param>
        public void Send_ScoreHelp(String nickname, Int32 tableId)
        {
            try
            {
                TcpClient client = new TcpClient(_serverIp, _serverPort);

                String message = ":" + tableId + ":" + MESSAGE_SCORE_HELP + ":" + nickname + "::";
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                NetworkStream stream = client.GetStream();

                stream.Write(data, 0, data.Length);

                stream.Close();
                client.Close();
            }
            catch (Exception)
            {
                _gameUI.HandleServerDownError();                
            }
        }

        /// <summary>
        /// Sends the server notification that the user wants to discard the 6 pack cards 
        /// </summary>
        /// <param name="nickname">the user's nickname</param>
        /// <param name="tableId">the game table id</param>
        /// <param name="cards">an array with the names of the new 6 cards</param>
        public void Send_DiscardCards(String nickname, Int32 tableId, List<CityCard> cards)
        {
            try
            {
                TcpClient client = new TcpClient(_serverIp, _serverPort);

                String message = ":" + tableId + ":" + MESSAGE_DISCARD_CARDS + ":" + nickname + ":";

                for (int i = 0; i < cards.Count; i++)
                    message = message + cards[i].CityName + "|";
                message = message + ":";

                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                NetworkStream stream = client.GetStream();

                stream.Write(data, 0, data.Length);

                stream.Close();
                client.Close();
            }
            catch (Exception)
            {
                _gameUI.HandleServerDownError();                
            }
        }

        /// <summary>
        /// Sends the server notification that the user wants to discard public cards
        /// </summary>
        /// <param name="nickname">the user's nickname</param>
        /// <param name="tableId">an array with the names of the public cards to be discarded</param>
        public void Send_DiscardPublicCards(String nickname, Int32 tableId)
        {
            try
            {
                TcpClient client = new TcpClient(_serverIp, _serverPort);

                String message = ":" + tableId + ":" + MESSAGE_DISCARD_PUBLIC_CARDS + ":" + nickname + "::";

                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                NetworkStream stream = client.GetStream();

                stream.Write(data, 0, data.Length);

                stream.Close();
                client.Close();
            }
            catch (Exception)
            {
                _gameUI.HandleServerDownError();
            }
        }

        /// <summary>
        /// Sends the server notification that the user has put houses on the game map
        /// </summary>
        /// <param name="nickname">the user's nickname</param>
        /// <param name="tableId">the game table id</param>
        /// <param name="cards">an array with the names of the citis the user put houses in</param>
        public void Send_PutHouses(String nickname, Int32 tableId, List<String> cards)
        {
            try
            {
                TcpClient client = new TcpClient(_serverIp, _serverPort);

                String message = ":" + tableId + ":" + MESSAGE_PUT_HOUSES + ":" + nickname + ":";

                for (int i = 0; i < cards.Count; i++)
                    message = message + cards[i] + "|";
                message = message + ":";

                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                NetworkStream stream = client.GetStream();

                stream.Write(data, 0, data.Length);

                stream.Close();
                client.Close();
            }
            catch (Exception)
            {
                _gameUI.HandleServerDownError();                
            }
        }
        
        /// <summary>
        /// Sends the server notification that the user quit the game
        /// </summary>
        /// <param name="nickname">the user's nickname</param>
        /// <param name="tableId">the game table id</param>
        /// <param name="type">0 if the user quit before the game ended, 1 otherwise</param>
        public void Send_Quit(String nickname, Int32 tableId, Int32 type)
        {
            try
            {
                TcpClient client = new TcpClient(_serverIp, _serverPort);

                String message = ":" + tableId + ":" + MESSAGE_QUIT + ":" + nickname + ":" + type + ":";
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                NetworkStream stream = client.GetStream();

                stream.Write(data, 0, data.Length);

                stream.Close();
                client.Close();
            }
            catch (Exception)
            {
                _gameUI.HandleServerDownError();             
            }
        }

        /// <summary>
        /// Handles the offer message
        /// </summary>
        /// <param name="nickname">the nickname of the user </param>
        /// <param name="data">the list of rooms</param>
        private void Received_Offer(String nickname, String data)
        {
            ArrayList roomList = new ArrayList();

            while (!data.Equals(""))
            {
                int val = data.IndexOf("|++");

                String table_data = data.Substring(0, val);
                data = data.Substring(val + 3);


                
                val = table_data.IndexOf("|");
                String id = table_data.Substring(0, val);
                table_data = table_data.Substring(val + 1);

                val = id.IndexOf("+");                
                String isStart = id.Substring(val + 1);
                id = id.Substring(0, val);

                val = table_data.IndexOf("||");
                String name = table_data.Substring(0, val);
                table_data = table_data.Substring(val + 2);

                List<String> playerList = new List<String>();
                playerList.Add(null);
                playerList.Add(null);
                playerList.Add(null);
                playerList.Add(null);

                int i = 0;
                while (!table_data.Equals(""))
                {
                    val = table_data.IndexOf("+");
                    String nick = table_data.Substring(0, val);
                    table_data = table_data.Substring(val + 1);
                    if (!nick.Equals("null"))
                        playerList[i] = nick;
                    i++;
                }
                Room r = new Room();
                r.ID = Convert.ToInt32(id);
                r.Name = name;
                r.ListPlayer = playerList;
                if (isStart.Equals("True"))
                    r.IsStarted = true;
                else
                    r.IsStarted = false;

                roomList.Add(r);
            }

            _gameUI.Received_Offer(nickname, roomList);
        }

        /// <summary>
        /// Handles the nack message
        /// </summary>
        private void Received_Nack()
        {
            _gameUI.Received_Nack();
        }

        /// <summary>
        /// Handles the ack join table message
        /// </summary>
        /// <param name="roomId">the id of the room</param>
        /// <param name="data">the list of the other players in the room</param>
        private void Received_AckJoinTable(String roomId, String data)
        {
            try
            {
                int _roomId = Convert.ToInt32(roomId);
                List<String> players = new List<String>();
                List<Boolean> states = new List<Boolean>();
                players.Add(null);
                players.Add(null);
                players.Add(null);
                players.Add(null);
                states.Add(false);
                states.Add(false);
                states.Add(false);
                states.Add(false);                

                data = data.Substring(1);
                int i = 0;
                while (!data.Equals("|"))
                {
                    int index = data.IndexOf("+");
                    String nick = data.Substring(0, index);
                    
                    data = data.Substring(index + 1);
                    index = data.IndexOf("+");
                    String type = data.Substring(0, index);
                    data = data.Substring(index + 1);                  
                    
                    if (!nick.Equals("null"))
                    {
                        if (type.Equals("True"))
                            states[i] = true;
                        else
                            states[i] = false;
                        players[i] = nick;
                    }
                    i++;
                }

                _gameUI.Received_AckJoinTable(_roomId, players, states);
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// Handles the nack join table message
        /// </summary>
        private void Received_NackJoinTable()
        {
            _gameUI.Received_NackJoinTable();
        }

        /// <summary>
        /// Handles the user join table message
        /// </summary>
        /// <param name="nickname">the nickname of the user </param>
        /// <param name="data">the position of the player in the room</param>
        private void Received_UserJoinTable(String nickname, String data)
        {
            try
            {
                int position = Convert.ToInt32(data);
                _gameUI.Received_UserJoinTable(nickname, position);
            }
            catch (Exception)
            {
                return;
            }
        }

        /// <summary>
        /// Handles the user start message
        /// </summary>
        /// <param name="nickname">the nickname of the user</param>
        private void Received_UserStart(String nickname)
        {
            _gameUI.Received_UserStart(nickname);
        }

        /// <summary>
        /// Handles the public discard cards message
        /// </summary>
        /// <param name="nickname"></param>
        private void Received_DiscardPublicCards(String nickname)
        {
            _gameUI.Received_DiscardPublicCards(nickname);
        }

        private void Received_UserCancel(String nickname)
        {
            _gameUI.Received_UserCancel(nickname);
        }

        private void Received_GameStart(String nickname, String data)
        {
            List<CityCard> cardList = new List<CityCard>();

            while (!data.Equals(""))
            {
                int val = data.IndexOf("|");
                String card_name = data.Substring(0, val);

                data = data.Substring(val + 1);

                cardList.Add(new CityCard(card_name));
            }

            _gameUI.Received_GameStart(nickname, cardList);
        }

        private void Received_UserTurn(String nickname)
        {
            _gameUI.Received_UserTurn(nickname);
        }

        private void Received_ChangeCards(String nickname, String data)
        {
            List<CityCard> cardList = new List<CityCard>();

            while (!data.Equals(""))
            {
                int val = data.IndexOf("|");
                String card_name = data.Substring(0, val);
                data = data.Substring(val + 1);

                cardList.Add(new CityCard(card_name));                
            }

            _gameUI.Received_ChangeCards(nickname, cardList);
        }

        private void Received_DrawCard(String nickname, String data)
        {   
            int val = data.IndexOf("|");
            String poz = data.Substring(0, val);
            data = data.Substring(val + 1);

            try
            {
                int position = Convert.ToInt32(poz);
                _gameUI.Received_DrawCard(nickname, position, data);
            }
            catch (Exception)
            {
                return;
            }
            
        }

        private void Received_PutCard(String nickname, String data)
        {
            int val = data.IndexOf("|");
            String poz = data.Substring(0, val);
            data = data.Substring(val + 1);

            try
            {
                int position = Convert.ToInt32(poz);
                _gameUI.Received_PutCard(nickname, position, data);
            }
            catch (Exception)
            {
                return;
            }
        }

        private void Received_Score(String nickname)
        {
            _gameUI.Received_Score(nickname);
        }

        private void Received_ScoreHelp(String nickname)
        {
            _gameUI.Received_ScoreHelp(nickname);
        }

        private void Received_DiscardCard(String nickname, String data)
        {
            List<String> cardNamesList = new List<String>();

            while (!data.Equals(""))
            {
                int val = data.IndexOf("|");
                String card_name = data.Substring(0, val);

                data = data.Substring(val + 1);

                cardNamesList.Add(card_name);
            }

            _gameUI.Received_DiscardCard(nickname, cardNamesList);
        }

        private void Received_PutHouses(String nickname, String data)
        {
            List<String> cardList = new List<String>();

            while (!data.Equals(""))
            {
                int val = data.IndexOf("|");
                String card_name = data.Substring(0, val);

                data = data.Substring(val + 1);

                cardList.Add(card_name);
            }

            _gameUI.Received_PutHouses(nickname, cardList);
        }

        private void Received_Quit(String nickname)
        {
            _gameUI.Received_Quit(nickname);
        }

        private void Received_AckCreateTable(String data)
        {
            try
            {                
                _gameUI.Received_AckCreateTable(Convert.ToInt32(data));
            }
            catch (Exception)
            {
            }

            
        }

        private void Received_NackCreateTable()
        {
            _gameUI.Received_NackCreateTable();
        }

        private void Received_Players_List(String data)
        {
            List<String> listPlayers = new List<String>();

            while (!data.Equals(""))
            {
                int val = data.IndexOf("+");
                String nick = data.Substring(0, val);
                data = data.Substring(val + 1);
                listPlayers.Add(nick);
            }

            _gameUI.Received_PlayersList(listPlayers);
        }

        private void Received_Disconnect()
        {
            _gameUI.Received_Disconnect();
        }

    }
}
